
///////////////////////////////////////////////////////////////////////////////
//
//  Copyright (c) 2009, Perry L Miller IV
//  All rights reserved.
//  BSD License: http://www.opensource.org/licenses/bsd-license.html
//  Derived from earlier work by Adam Kubach and Perry Miller found here:
//  http://sourceforge.net/projects/cadkit/
//
///////////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////////
//
//  Class that represents a toolbar.
//
///////////////////////////////////////////////////////////////////////////////

#include "Helios/Menus/ToolBar.h"

#include "Usul/Functions/NoThrow.h"

#include <algorithm>

using namespace Helios::Menus;


///////////////////////////////////////////////////////////////////////////////
//
//  Constructor
//
///////////////////////////////////////////////////////////////////////////////

ToolBar::ToolBar ( const std::string &name ) : BaseClass ( name ), 
  _buttons(),
  _needToRebuild ( true ),
  _needToUpdate ( true )
{
}


///////////////////////////////////////////////////////////////////////////////
//
//  Destructor
//
///////////////////////////////////////////////////////////////////////////////

ToolBar::~ToolBar()
{
  USUL_TRY_BLOCK
  {
    _buttons.clear();
  }
  USUL_DEFINE_CATCH_BLOCKS ( "3404654533" );
}


///////////////////////////////////////////////////////////////////////////////
//
//  Find the button.
//
///////////////////////////////////////////////////////////////////////////////

ToolBar::Position ToolBar::find ( Button::RefPtr button ) const
{
  Guard guard ( this );
  ButtonList::const_iterator i ( std::find ( _buttons.begin(), _buttons.end(), button ) );
  return ( ( _buttons.end() == i ) ? -1 : std::distance ( _buttons.begin(), i ) );
}


///////////////////////////////////////////////////////////////////////////////
//
//  Helper predicate for finding the button with given text.
//
///////////////////////////////////////////////////////////////////////////////

namespace Helper
{
  struct HasText
  {
    HasText ( const std::string &text ) : _text ( text ){}
    bool operator () ( const Helios::Menus::Button::RefPtr &button )
    {
      return ( ( true == button.valid() ) ? ( button->text() == _text ) : false );
    }
  private:
    const std::string _text;
  };
}


///////////////////////////////////////////////////////////////////////////////
//
//  Find the button.
//
///////////////////////////////////////////////////////////////////////////////

ToolBar::Position ToolBar::find ( const std::string &text ) const
{
  Guard guard ( this );
  ButtonList::const_iterator i ( std::find_if 
    ( _buttons.begin(), _buttons.end(), Helper::HasText ( text ) ) );
  return ( ( _buttons.end() == i ) ? -1 : std::distance ( _buttons.begin(), i ) );
}


///////////////////////////////////////////////////////////////////////////////
//
//  Remove the button.
//
///////////////////////////////////////////////////////////////////////////////

void ToolBar::remove ( Position i )
{
  Guard guard ( this );

  if ( ( i < 0 ) || ( i > _buttons.size() ) )
    return;

  _buttons.erase ( _buttons.begin() + i );
}


///////////////////////////////////////////////////////////////////////////////
//
//  Insert the button.
//
///////////////////////////////////////////////////////////////////////////////

void ToolBar::insert ( Position i, Button::RefPtr button )
{
  Guard guard ( this );

  if ( false == button.valid() )
    return;

  if ( ( -1 == i ) || ( i > _buttons.size() ) )
    i = _buttons.size();

  _buttons.insert ( _buttons.begin() + i, button );
}


///////////////////////////////////////////////////////////////////////////////
//
//  Set the flag.
//
///////////////////////////////////////////////////////////////////////////////

void ToolBar::needToRebuild ( bool state )
{
  Guard guard ( this );
  _needToRebuild = state;
}


///////////////////////////////////////////////////////////////////////////////
//
//  Do we need to rebuild?
//
///////////////////////////////////////////////////////////////////////////////

bool ToolBar::needToRebuild() const
{
  Guard guard ( this );
  return _needToRebuild;
}


///////////////////////////////////////////////////////////////////////////////
//
//  Set the flag.
//
///////////////////////////////////////////////////////////////////////////////

void ToolBar::needToUpdate ( bool state )
{
  Guard guard ( this );
  _needToUpdate = state;
}


///////////////////////////////////////////////////////////////////////////////
//
//  Do we need to rebuild?
//
///////////////////////////////////////////////////////////////////////////////

bool ToolBar::needToUpdate() const
{
  Guard guard ( this );
  return _needToUpdate;
}


///////////////////////////////////////////////////////////////////////////////
//
//  Visit the items.
//
///////////////////////////////////////////////////////////////////////////////

void ToolBar::visitItems ( Visitor &v )
{
  Guard guard ( this );
  for ( ButtonList::iterator i = _buttons.begin(); i != _buttons.end(); ++i )
  {
    Button::RefPtr b ( *i );
    if ( true == b.valid() )
    {
      b->accept ( v );
    }
  }
}


///////////////////////////////////////////////////////////////////////////////
//
//  Is the menu empty?
//
///////////////////////////////////////////////////////////////////////////////

bool ToolBar::empty() const
{
  Guard guard ( this );
  return _buttons.empty();
}
